package com.tfswx.fljdmxyy.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.newbie.core.exception.BusinessException;
import com.tfswx.fljdmxyy.constant.SystemConstant;
import com.tfswx.fljdmxyy.dao.ZzjgXtDwMapper;
import com.tfswx.fljdmxyy.dto.dwgl.*;
import com.tfswx.fljdmxyy.dto.pzgl.PzxGetInputDTO;
import com.tfswx.fljdmxyy.dto.pzgl.PzxGetOutputDTO;
import com.tfswx.fljdmxyy.dto.rygl.RyxxAddInputDTO;
import com.tfswx.fljdmxyy.dto.rygl.RyxxAddOutputDTO;
import com.tfswx.fljdmxyy.dto.rygl.RyxxOutputDTO;
import com.tfswx.fljdmxyy.enums.BusinessCodeEnum;
import com.tfswx.fljdmxyy.model.ZzjgXtDw;
import com.tfswx.fljdmxyy.query.dwgl.DwxxQueryParam;
import com.tfswx.fljdmxyy.query.dwgl.DwxxQueryResult;
import com.tfswx.fljdmxyy.query.dwgl.ZzjgQueryParam;
import com.tfswx.fljdmxyy.query.dwgl.ZzjgQueryResult;
import com.tfswx.fljdmxyy.service.DwglService;
import com.tfswx.fljdmxyy.service.PzglService;
import com.tfswx.fljdmxyy.service.RyglService;
import com.tfswx.fljdmxyy.service.SjzdService;
import com.tfswx.fljdmxyy.utils.ConverterUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 单位管理实现类
 *
 * @author 唐晓宇
 * @date 2023/03/24
 */
@Slf4j
@Service
public class DwglServiceImpl implements DwglService {

    @Resource
    private ZzjgXtDwMapper zzjgXtDwMapper;

    @Resource
    private RyglService ryglService;

    @Resource
    private PzglService pzglService;

    @Resource
    private SjzdService sjzdService;

    @Value("${tyyw.url}")
    private String tyywUrl;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DwxxAddOutputDTO addDwxx(DwxxAddInputDTO dto) {
        ZzjgXtDw dwxx = ConverterUtils.convert(dto, ZzjgXtDw.class);
        // 1.查询单位是否存在
        ZzjgXtDw zzjgXtDw = zzjgXtDwMapper.getZzjgXtDw(dwxx);
        if (ObjectUtil.isNotNull(zzjgXtDw)) {
            throw new BusinessException(BusinessCodeEnum.TJSJSB.getCode(), "单位已经存在，单位编码：" + dwxx.getDwbm());
        }
        Date now = new Date();
        dwxx.setCjsj(now);
        dwxx.setZhxgsj(now);
        dwxx.setSfsc(SystemConstant.N);

        // 2.尝试修改当前单位编码的是否删除为N
        Integer updateNum = zzjgXtDwMapper.updateZzjgXtDw(dwxx);

        // 3.如果修改失败，则新增当前单位编码
        Integer insertNum = 0;
        if (updateNum <= 0) {
            insertNum = zzjgXtDwMapper.insertZzjgXtDw(dwxx);

            // 4.新增一个该单位管理员
            addGly(dwxx);
        }

        // 5.如果修改、新增都失败则抛错
        if (insertNum + updateNum <= 0) {
            throw new BusinessException(BusinessCodeEnum.TJSJSB);
        }
        return ConverterUtils.convert(dwxx, DwxxAddOutputDTO.class);
    }

    /**
     * 新增单位时初始化一位登录别名为"admin"的管理员
     *
     * @param dwxx
     */
    private void addGly(ZzjgXtDw dwxx) {
        // 1.获取配置的管理员登录别名
        PzxGetInputDTO getGlydlbm = new PzxGetInputDTO();
        getGlydlbm.setPzxbm("xtpz.glydlbm");
        PzxGetOutputDTO glydlbmPzx = pzglService.getPzx(getGlydlbm);

        // 2.获取配置的管理员角色编码
        PzxGetInputDTO getGlyjsbm = new PzxGetInputDTO();
        getGlyjsbm.setPzxbm("xtpz.glyjsbm");
        PzxGetOutputDTO glyjsbmPzx = pzglService.getPzx(getGlyjsbm);

        // 3.获取配置的管理员名称
        PzxGetInputDTO getGlymc = new PzxGetInputDTO();
        getGlymc.setPzxbm("xtpz.glymc");
        PzxGetOutputDTO glymcPzx = pzglService.getPzx(getGlymc);

        // 4.获取配置的数据来源
        PzxGetInputDTO getSjly = new PzxGetInputDTO();
        getSjly.setPzxbm("xtpz.sjlyBxt");
        PzxGetOutputDTO bxtPzx = pzglService.getPzx(getSjly);

        // 5.新增人员
        RyxxAddInputDTO ryxxAddInputDTO = new RyxxAddInputDTO();
        ryxxAddInputDTO.setDwbm(dwxx.getDwbm());
        ryxxAddInputDTO.setDwmc(dwxx.getDwmc());
        ryxxAddInputDTO.setDlbm(glydlbmPzx.getPzxz());
        ryxxAddInputDTO.setJsbm(glyjsbmPzx.getPzxz());
        ryxxAddInputDTO.setRymc(glymcPzx.getPzxz());
        ryxxAddInputDTO.setSjly(bxtPzx.getPzxz());
        RyxxAddOutputDTO ryxxAddOutputDTO = ryglService.addRyxx(ryxxAddInputDTO);
        if (ObjectUtils.isEmpty(ryxxAddOutputDTO)) {
            throw new BusinessException(BusinessCodeEnum.TJSJSB.getCode(), "初始化单位管理员失败");
        }
    }

    @Override
    public DwxxGetOutputDTO getDwxx(DwxxGetInputDTO dto) {
        ZzjgXtDw dwxx = ConverterUtils.convert(dto, ZzjgXtDw.class);
        return ConverterUtils.convert(zzjgXtDwMapper.getZzjgXtDw(dwxx), DwxxGetOutputDTO.class);
    }

    @Override
    public DwxxUpdateOutputDTO updateDwxx(DwxxUpdateInputDTO dto) {
        ZzjgXtDw dwxx = ConverterUtils.convert(dto, ZzjgXtDw.class);
        // 1.判断单位是否存在
        ZzjgXtDw zzjgXtDw = zzjgXtDwMapper.getZzjgXtDw(dwxx);
        if (ObjectUtil.isNull(zzjgXtDw)) {
            throw new BusinessException(BusinessCodeEnum.HQSJSB.getCode(), "单位不存在，单位编码：" + dwxx.getDwbm());
        }

        // 2.修改单位信息
        dwxx.setZhxgsj(new Date());
        Integer result = zzjgXtDwMapper.updateZzjgXtDw(dwxx);
        if (result <= 0) {
            throw new BusinessException(BusinessCodeEnum.XGSJSB);
        }
        return ConverterUtils.convert(dwxx, DwxxUpdateOutputDTO.class);
    }

    @Override
    public DwxxDeleteOutputDTO deleteDwxx(DwxxDeleteInputDTO dto) {
        ZzjgXtDw dwxx = new ZzjgXtDw();
        dwxx.setDwbm(dto.getDwbm());
        dwxx.setZhxgsj(new Date());
        Integer result = zzjgXtDwMapper.deleteZzjgXtDw(dwxx);
        if (result <= 0) {
            throw new BusinessException(BusinessCodeEnum.SCSJSB);
        }
        return ConverterUtils.convert(dwxx, DwxxDeleteOutputDTO.class);
    }

    @Override
    public List<DwxxQueryResult> queryDwxx() {
        List<ZzjgXtDw> dwList = zzjgXtDwMapper.queryZzjgXtDw(null);
        return ConverterUtils.convertList(dwList, DwxxQueryResult.class);
    }

    @Override
    public List<ZzjgQueryResult> queryZzjg(ZzjgQueryParam param) {
        // 1.调用统一业务查询单位树
        String response = HttpRequest.post(tyywUrl + SystemConstant.GET_UNIT_TREE)
                                     .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                                     .timeout(-1).body(JSONUtil.toJsonStr(param)).execute().body();

        // 2.如果请求结果为空则抛错
        if (StrUtil.isBlank(response)) {
            throw new BusinessException(BusinessCodeEnum.HQSJSB);
        }

        // 3.解析为JSON对象
        JSONObject result = JSON.parseObject(response);
        if (result.getBoolean("success")) {
            JSONArray array = (JSONArray) result.get("data");
            if (CollUtil.isNotEmpty(array)) {
                return array.toJavaList(ZzjgQueryResult.class);
            } else {
                return new ArrayList<>();
            }
        } else {
            throw new BusinessException(BusinessCodeEnum.HQSJSB);
        }
    }

    @Override
    public List<DwxxQueryResult> queryDwlb(DwxxQueryParam param) {
        String dwbm = param.getDwbm();
        // 1.如果未传入单位编码，则获取当前登录人单位
        if (StringUtils.isBlank(dwbm)) {
            RyxxOutputDTO ryxxOutputDTO = ryglService.getUserInfo();
            if (ObjectUtils.isEmpty(ryxxOutputDTO)) {
                throw new BusinessException(BusinessCodeEnum.HQSJSB);
            }
            dwbm = ryxxOutputDTO.getDwbm();
            if (StringUtils.isBlank(dwbm)) {
                throw new BusinessException(BusinessCodeEnum.HQSJSB);
            }
            param.setDwbm(dwbm);
        }

        // 2.查询当前单位及其下级单位
        return queryXjdwlb(param);
    }

    /**
     * 查询当前单位及其下级单位
     *
     * @param param
     * @return List<DwxxQueryResult>
     */
    public List<DwxxQueryResult> queryXjdwlb(DwxxQueryParam param) {
        // 1.查询全部单位
        List<DwxxQueryResult> results = zzjgXtDwMapper.queryDwlb(param);

        // 2.初始化下级单位列表
        List<DwxxQueryResult> resultList = new ArrayList<>();

        // 3.将本院加入列表中
        resultList.addAll(results.stream().filter(item ->
                CharSequenceUtil.equals(item.getDwbm(), param.getDwbm())).collect(Collectors.toList()));

        // 4.递归查询当前单位编码的下级单位
        queryXjdwlb(param.getDwbm(), results, resultList);

        // 5.排序
        CollUtil.sort(resultList, Comparator.comparing(DwxxQueryResult::getDwbm));

        return resultList;
    }

    /**
     * 递归查询当前单位编码的下级单位
     *
     * @param dwbm       当前单位编码
     * @param dwlb       所有单位列表
     * @param resultList 下级单位列表
     */
    public void queryXjdwlb(String dwbm, List<DwxxQueryResult> dwlb, List<DwxxQueryResult> resultList) {
        // 1.获取下级单位
        List<DwxxQueryResult> xjdwList = dwlb.stream().filter(item ->
                CharSequenceUtil.equals(dwbm, item.getFdwbm())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(xjdwList)) {
            // 2.下级单位放入结果集中
            resultList.addAll(xjdwList);
            xjdwList.forEach(item -> {
                // 3.获取下级单位的下级单位
                queryXjdwlb(item.getDwbm(), dwlb, resultList);
            });
        }
    }
}
